package com.csdig.cms.utils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaProperty;
import org.apache.commons.beanutils.PropertyUtilsBean;

public class PropertiCopier extends PropertyUtilsBean {

	private static PropertiCopier instance;

	public static PropertiCopier getInstance() {
		if (instance == null) {
			instance = new PropertiCopier();
		}
		return instance;
	}

	public void copyExcludeNull(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException,
			NoSuchMethodException {

		if (dest == null) {
			throw new IllegalArgumentException("No destination bean specified");
		}
		if (orig == null) {
			throw new IllegalArgumentException("No origin bean specified");
		}
		if (orig instanceof DynaBean) {
			DynaProperty[] origDescriptors = ((DynaBean) orig).getDynaClass().getDynaProperties();
			for (int i = 0; i < origDescriptors.length; i++) {
				String name = origDescriptors[i].getName();
				if (isReadable(orig, name) && isWriteable(dest, name)) {
					try {
						Object value = ((DynaBean) orig).get(name);
						if (value == null)
							continue;
						if (dest instanceof DynaBean) {
							((DynaBean) dest).set(name, value);
						} else {
							setSimpleProperty(dest, name, value);
						}
					} catch (NoSuchMethodException e) {
					}
				}
			}
		} else if (orig instanceof Map) {
			Iterator<?> entries = ((Map<?, ?>) orig).entrySet().iterator();
			while (entries.hasNext()) {
				Map.Entry<?, ?> entry = (Map.Entry<?, ?>) entries.next();
				String name = (String) entry.getKey();
				Object value = entry.getValue();
				if (value == null)
					continue;
				if (isWriteable(dest, name)) {
					try {
						if (dest instanceof DynaBean) {
							((DynaBean) dest).set(name, entry.getValue());
						} else {
							setSimpleProperty(dest, name, entry.getValue());
						}
					} catch (NoSuchMethodException e) {
					}
				}
			}
		} else /* if (orig is a standard JavaBean) */{
			PropertyDescriptor[] origDescriptors = getPropertyDescriptors(orig);
			for (int i = 0; i < origDescriptors.length; i++) {
				String name = origDescriptors[i].getName();
				if (isReadable(orig, name) && isWriteable(dest, name)) {
					try {
						Object value = getSimpleProperty(orig, name);
						if (value == null)
							continue;
						if (dest instanceof DynaBean) {
							((DynaBean) dest).set(name, value);
						} else {
							setSimpleProperty(dest, name, value);
						}
					} catch (NoSuchMethodException e) {
					}
				}
			}
		}

	}

}
